package com.softserveinc.moviedbapp.appwidget;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.widget.RemoteViews;

import com.softserveinc.moviedbapp.R;
import com.softserveinc.moviedbapp.application.MovieDBApplication;
import com.softserveinc.moviedbapp.manager.BitMapManager;
import com.softserveinc.moviedbapp.model.Movie;
import com.softserveinc.moviedbapp.util.MovieAppConstants;

import java.util.ArrayList;
import java.util.List;

public class MovieWidgetProvider extends AppWidgetProvider {

	private static final String TAG = MovieWidgetProvider.class.getSimpleName();
	private BitMapManager bitmapManager;

	@Override
	public void onReceive(final Context context, final Intent intent) {
		if (bitmapManager == null) {
			bitmapManager = ((MovieDBApplication) context.getApplicationContext()).getBitMapManager();
		}
		String action = intent.getAction();
		Log.e(TAG, "in onReceive() and action is " + action);
		if (action.equals(UpdateService.INTENT_UPDATE_YOURSELF)) {
			updateWidget(context, intent);
		} else {
			super.onReceive(context, intent);
		}
	}

	@Override
	public void onDeleted(final Context context, final int[] appWidgetIds) {
		Log.e(TAG, "in onDeleted() setting alarm to -1");
		SharedPreferences prefs = context.getSharedPreferences(WidgetPreferencesConstants.PREFS_FILE, 0);
		Editor editor = prefs.edit();
		for (int appWidgetId : appWidgetIds) {
			setAlarm(context, appWidgetId, -1);
			removeWidgetSettings(editor, appWidgetId);
		}
	}

	@Override
	public void onDisabled(final Context context) {
		Log.e(TAG, "in onDisabled() stopping service");
		context.stopService(new Intent(context, UpdateService.class));
	}

	public static void setAlarm(final Context context, final int appWidgetId, final int updateRate) {
		PendingIntent newPendingIntent = createPendingIntent(context, UpdateService.UPDATE, appWidgetId);
		AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
		if (updateRate >= 0) {
			Log.d(TAG, "inside setAlarm() setting alarms.setRepeating to update rate " + updateRate);
			/* This alarm does not wake the device up; if it goes off while the device is asleep, it will not be
			 * delivered until the next time the device wakes up */
			alarms.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + updateRate, updateRate,
					newPendingIntent);
		} else {
			// on a negative updateRate stop the refreshing
			alarms.cancel(newPendingIntent);
		}
	}

	public static PendingIntent createPendingIntent(final Context context, final String action, final int appWidgetId) {
		Intent intent;
		if (action.equals(UpdateService.CONFIGURE)) {
			intent = new Intent(context, com.softserveinc.moviedbapp.appwidget.WidgetConfigurePreferenceActivity.class);
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			intent.setAction(action);
			intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
			Log.d(TAG, "in createPendingIntent() action is " + action);
			// this Uri data is to make the PendingIntent unique, so it wont be updated by FLAG_UPDATE_CURRENT
			// so if there are multiple widget instances they wont override each other
			Uri data = Uri.withAppendedPath(Uri.parse("moviewidget://widget/id/#" + action + appWidgetId),
					String.valueOf(appWidgetId));
			intent.setData(data);
			return (PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
		} else {
			intent = new Intent(context, UpdateService.class);
			intent.setAction(action);
			intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
			Log.d(TAG, "in createPendingIntent() action is " + action);
			// this Uri data is to make the PendingIntent unique, so it wont be updated by FLAG_UPDATE_CURRENT
			// so if there are multiple widget instances they wont override each other
			Uri data = Uri.withAppendedPath(Uri.parse("moviewidget://widget/id/#" + action + appWidgetId),
					String.valueOf(appWidgetId));
			intent.setData(data);
			return (PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
		}
	}

	public static PendingIntent createPendingIntentMovieDetails(final Context context, final String action,
			final Movie movie, final int requestCode, final int appWidgetId) {
		Intent intent = new Intent(context, com.softserveinc.moviedbapp.application.MovieDBMainActivity.class);
		intent.setAction(action);
		Uri data = Uri.parse(movie.toString());
		intent.setData(data);
		intent.putExtra(MovieAppConstants.MOVIE_OBJECT, movie);
		Log.d(TAG, "in createPendingIntent() action is " + action);

		return (PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT));
	}

	private void updateWidget(final Context context, final Intent intent) {
		Log.d(TAG, "in updateWidget() and action is " + intent.getAction());
		// Push update for this widget to the home screen
		AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
		Bundle movieBundle = intent.getBundleExtra(MovieAppConstants.MOVIE_ITEMS);
		List<Movie> movies = new ArrayList<Movie>();
		for (int i = 0; i < movieBundle.size(); i++) {
			movies.add((Movie) movieBundle.getParcelable(MovieAppConstants.MOVIE_OBJECT + i));
		}
		int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

		SharedPreferences prefs = context.getSharedPreferences(WidgetPreferencesConstants.PREFS_FILE, 0);
		int updateRateList = prefs.getInt(WidgetPreferencesConstants.UPDATE_NEXT_LIST + appWidgetId, 30);
		int updateRateMovie = prefs.getInt(WidgetPreferencesConstants.UPDATE_NEXT_MOVIE + appWidgetId, 5);

		Log.d(TAG, "in updateWidget() setting alarm to update rate " + updateRateList * 1000 * 60);
		setAlarm(context, appWidgetId, updateRateList * 1000 * 60);

		RemoteViews remoteViews = buildUpdate(context, appWidgetId, movies, updateRateMovie);
		// apply changes to widget
		appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
	}

	private RemoteViews buildUpdate(final Context context, final int appWidgetId, final List<Movie> movies, final int updateRateMovie) {
		Log.d(TAG, "buildUpdate() building...");
		RemoteViews flipper = new RemoteViews(context.getPackageName(), R.layout.movie_widget_flipper);
		int requestCode = 0;
		for (Movie currentMovie : movies) {
			RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.movie_widget_layout);
			/* set the poster url */
			// TODO figure out how to make transitions smooth if posters are not cached yet
			Bitmap posterBitmap = bitmapManager.fetchBitmap(currentMovie.getThumbPosterUrl());
			if (posterBitmap != null) {
				updateViews.setImageViewBitmap(R.id.widget_poster, posterBitmap);
			} else {
				updateViews.setImageViewResource(R.id.widget_poster, R.drawable.not_available);
			}
			/* set movie title and release date and rating */
			updateViews.setTextViewText(R.id.widget_movieName, currentMovie.getName());
			updateViews.setTextViewText(R.id.widget_releaseDate, currentMovie.getReleased());
			updateViews.setTextViewText(R.id.widget_rating, String.valueOf(currentMovie.getRating()));

			/* set the proper certification image */
			if (currentMovie.getCertification().equals("PG-13")) {
				updateViews.setImageViewResource(R.id.widget_certification, R.drawable.rating_pg13);
			} else if (currentMovie.getCertification().equals("R")) {
				updateViews.setImageViewResource(R.id.widget_certification, R.drawable.rating_r);
			} else if (currentMovie.getCertification().equals("NR")) {
				updateViews.setImageViewResource(R.id.widget_certification, R.drawable.rating_nr);
			} else if (currentMovie.getCertification().equals("PG")) {
				updateViews.setImageViewResource(R.id.widget_certification, R.drawable.rating_pg);
			} else if (currentMovie.getCertification().equals("G")) {
				updateViews.setImageViewResource(R.id.widget_certification, R.drawable.rating_g);
			} else {
				updateViews.setImageViewResource(R.id.widget_certification, R.drawable.rating_nr);
			}
			/* set onClick listener to show movie details */
			updateViews.setOnClickPendingIntent(R.id.widget_info_area, MovieWidgetProvider
					.createPendingIntentMovieDetails(context, UpdateService.SHOW_MOVIE_DETAILS, currentMovie, requestCode, appWidgetId));
			requestCode++;
			updateViews.setOnClickPendingIntent(R.id.widget_configure_btn,
					MovieWidgetProvider.createPendingIntent(context, UpdateService.CONFIGURE, appWidgetId));

			flipper.addView(R.id.app_widget_flipper, updateViews);
		}
		/* set flipping interval via reflection */
		flipper.setInt(R.id.app_widget_flipper, "setFlipInterval", updateRateMovie * 1000);
		return flipper;
	}

	/* removes widget's settings from shared preferences */
	private void removeWidgetSettings(final Editor editor, final int appWidgetId) {
		Log.d(TAG, "in removeWidgetSettings() removing widget's settings " + appWidgetId);
		editor.remove("updateNextMovie" + appWidgetId);
		editor.remove("updateMovieList" + appWidgetId);
		editor.remove("results" + appWidgetId);
		editor.remove("orderBy" + appWidgetId);

		editor.commit();
	}
}
